﻿using SuperJoe.Framework.Core.Exceptions;
using SuperJoe.Framework.Logging;
using System;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using WWX.MemberPortal.Web.Common;

namespace WWX.MemberPortal.Web.Filters
{
    public class CustomHandleExceptionAttribute : HandleErrorAttribute
    {
        public override void OnException(ExceptionContext filterContext)
        {
            MethodInfo actionMethod = null;
            Type controllerType = null;

            GetControllerAndAction(filterContext, out controllerType, out actionMethod);

            if (actionMethod.ReturnType == typeof(JsonResult))
            {
                var friendlyException = filterContext.Exception as UserFriendlyException;
                string errorMessage = string.Empty;

#if DEBUG
                {
                    errorMessage = (friendlyException != null ? friendlyException.FriendlyMessage : filterContext.Exception.ToString());
                }
#else
                {
                    errorMessage = (friendlyException != null ? friendlyException.FriendlyMessage : "系统异常，请联系管理员");
                }
#endif
                filterContext.Result = JsonResultHelper.CreateRichJsonResult(false, errorMessage);
            }
            else if (actionMethod.ReturnType == typeof(ActionResult) || actionMethod.ReturnType == typeof(ViewResult))
            {
                filterContext.Result = new ViewResult() { ViewName = "error", ViewData = filterContext.Controller.ViewData };
                filterContext.Controller.ViewData.Model =
                new ErrorInfo() { Exception = filterContext.Exception, ControllerName = controllerType.Name, Action = actionMethod.Name, Message = filterContext.Exception.Message };
            }

            filterContext.ExceptionHandled = true;

            LoggerUtil.Error(controllerType.FullName + "." + actionMethod.Name + "执行失败", filterContext.Exception);
        }

        private void GetControllerAndAction(ExceptionContext filterContext, out Type controllerType, out MethodInfo actionMethod)
        {
            actionMethod = null;
            controllerType = filterContext.Controller.GetType();

            var actionName = filterContext.RouteData.Values["action"].ToString();
            var publicMethods = controllerType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
            var actionMethods = publicMethods.Where(m => m.Name.ToLower() == actionName.ToLower()).ToList();

            if (actionMethods.Count == 1)
            {
                actionMethod = actionMethods[0];
            }
            else
            {
                bool isGet = filterContext.HttpContext.Request.HttpMethod.ToLower() == "get";

                foreach (var method in actionMethods)
                {
                    var postAttr = method.GetCustomAttribute<HttpPostAttribute>();

                    if (postAttr == null && isGet)
                    {
                        actionMethod = method;
                        break;
                    }

                    if (postAttr != null && !isGet)
                    {
                        actionMethod = method;
                        break;
                    }
                }
            }
        }
    }
}